package is.server.model.xtool;

import is.common.exception.DroppingNonEmptyDepartmentException;
import is.common.exception.RowNotFoundException;
import is.common.exception.RowsAreaIncorrectException;
import is.common.exception.UniqueCheckFailedException;
import is.common.interfaces.SectionAdapter;
import is.common.util.Regex;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * @author aspr0
 *         Date: 17.04.12
 *         Time: 15:19
 */
public class DepartmentSectionAdapter extends AbstractSectionAdapter implements SectionAdapter
{
    public DepartmentSectionAdapter(Node section, NodeList rows, SectionArbiter sectionArbiter)
    {
        super(section, rows, sectionArbiter);
    }

    @Override
    protected String[][] getRowsReplacementsMade(int rowNumStart, int howMany) throws RowNotFoundException
    {
        String[][] rowsStrings = new String[howMany][Name.Out.Department.entries.length];

        for (int rowNum = rowNumStart; rowNum < rowNumStart + howMany; rowNum++)
        {
            /* starting output row */
            int entryOutputNum = 0;

            for (int entryNum = 0; entryNum < Name.Tag.Department.entries.length; entryNum++)
            {
                String entryValue = rows.item(rowNum).getChildNodes().item(entryNum).getTextContent();

                switch (entryNum)
                {
                    case 2:
                        String bossLastName = "";
                        String bossFirstName = "";
                        String bossMiddleName = "";

                        if (!entryValue.isEmpty())
                        {
                            try
                            {
                                String[] bossName = sectionArbiter.getEmployeeName(entryValue);
                                bossLastName = bossName[0];
                                bossFirstName = bossName[1];
                                bossMiddleName = bossName[2];
                            }
                            catch (RowNotFoundException e)
                            {
                                /* bossName remains empty if boss was dropped */
                            }
                        }

                        rowsStrings[rowNum][entryOutputNum++] = bossLastName;
                        rowsStrings[rowNum][entryOutputNum++] = bossFirstName;
                        rowsStrings[rowNum][entryOutputNum++] = bossMiddleName;
                        break;

                    default:
                        rowsStrings[rowNum][entryOutputNum++] = entryValue;
                        break;
                }
            }
        }
        return rowsStrings;
    }

    /**
     * @param rowNumStart
     * @param howMany     below zero to get all rows
     * @return
     * @throws is.common.exception.RowsAreaIncorrectException
     *
     */
    @Override
    public String[][] getRows(int rowNumStart, int howMany) throws RowsAreaIncorrectException, RowNotFoundException
    {
        if (howMany < 1)
        {
            howMany = rowCount;
        }

        rowsAreaExists(rowNumStart, howMany, rowCount);

        return getRowsReplacementsMade(rowNumStart, howMany);
    }

    @Override
    public String[] getHeader()
    {
        return Name.Out.Department.entries;
    }

    @Override
    public void addRow(String[] row) throws RowNotFoundException, UniqueCheckFailedException
    {
        String name = row[0];

        nameUnique(name);

        NodeList createdRow = createRow();

        String id = getId();
        incId();
        updateRowCount();

        createdRow.item(0).setTextContent(id);
        createdRow.item(1).setTextContent(name);
    }

    @Override
    public void editRow(String[] rowStrings) throws RowNotFoundException, UniqueCheckFailedException
    {
        String id = rowStrings[0];
        String name = rowStrings[1];
        String bossId = rowStrings[2];

        nameUniqueExceptCurrentId(id, name);

        boolean bossIdNumeric = Regex.stringMatches(bossId, "\\d*");

        if (!bossId.isEmpty() && bossIdNumeric)
        {
            bossIdExists(bossId);
            bossIsFromCurrentDepartment(bossId, id);
        }

        NodeList rowNodeList = getRowById(id);

//        rowStrings[2] = sectionArbiter.getEmployeeId(bossLastName, bossFirstName, bossMiddleName);
//        rowStrings = Arrays.copyOf(rowStrings, 3);

        rowNodeList.item(1).setTextContent(name);

        if (bossIdNumeric)
        {
            rowNodeList.item(2).setTextContent(bossId);
        }
    }


    public String dropRows(String[] rowIds) throws DroppingNonEmptyDepartmentException
    {
        for (String rowId : rowIds)
        {
            if (!sectionArbiter.isDepartmentEmpty(rowId))
            {
                throw new DroppingNonEmptyDepartmentException();
            }
        }

        return super.dropRows(rowIds);
    }

    @Override
    public Node createSection()
    {
        return sectionArbiter.createDomElement(Name.Tag.Department.section);
    }

    public NodeList createRow()
    {
        return super.createRow(Name.Tag.Department.entries);
    }

    public String getDepartmentName(String departmentId) throws RowNotFoundException
    {
        for (int i = 0; i < rowCount; i++)
        {
            String currentDepartmentId = rows.item(i).getChildNodes().item(0).getTextContent();
            String currentDepartmentName = rows.item(i).getChildNodes().item(1).getTextContent();

            if (departmentId.equals(currentDepartmentId))
            {
                return currentDepartmentName;
            }

        }
        throw new RowNotFoundException();
    }

    public String getId(String departmentName) throws RowNotFoundException
    {
        for (int rowNum = 0; rowNum < rowCount; rowNum++)
        {
            NodeList entries = rows.item(rowNum).getChildNodes();
            String id = entries.item(0).getTextContent();
            String name = entries.item(1).getTextContent();

            if (name.equals(departmentName))
            {
                return id;
            }
        }
        throw new RowNotFoundException();
    }

    private void nameUnique(String name) throws UniqueCheckFailedException
    {
        if (isThereSuchEntry(1, name))
        {
            throw new UniqueCheckFailedException();
        }
    }

    protected void nameUniqueExceptCurrentId(String id, String name) throws UniqueCheckFailedException
    {
        for (int rowNum = 0; rowNum < rowCount; rowNum++)
        {
            NodeList entries = rows.item(rowNum).getChildNodes();
            String currentId = entries.item(0).getTextContent();
            String currentName = entries.item(1).getTextContent();

            if (!currentId.equals(id))
            {
                if (currentName.equals(name))
                {
                    throw new UniqueCheckFailedException();
                }
            }
        }
    }

    private void bossIdExists(String bossId) throws RowNotFoundException
    {
        sectionArbiter.employeeIdExists(bossId);
    }


    private void bossIdUnique(String bossId) throws UniqueCheckFailedException
    {
        if (isThereSuchEntry(2, bossId))
        {
            throw new UniqueCheckFailedException();
        }
    }

    private void bossIsFromCurrentDepartment(String bossId, String id) throws RowNotFoundException
    {
        sectionArbiter.employeeInDepartment(bossId, id);
    }
}
